#!/usr/bin/env python

'''
  MUDServ - A Multi-User Dungeon Server
  Web Server Source Code
  
  Copyright (c) 2009, Ecl3ctic Software
  All rights reserved.
  
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
  * Neither the name of Ecl3ctic Software nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
'''

import socket
import sys
import os
import logging
import threading
import traceback
import model
import simplejson
import urllib
from time import sleep
from random import *
from mimetypes import guess_type
from wsgiref.simple_server import make_server
from clientlib import *
from elixir import *

class WebServ(threading.Thread):
  def __init__(self, port, server_port):
    '''
      Web server init
      
      port: The port to serve web pages on
      server_port: The server port to connect to
    '''
    threading.Thread.__init__(self)
    self.port = port
    self.server_port = server_port
    self.sock = None
    self.httpd = None
    self.killed = False
    
  def kill(self):
    self.killed = True
    
    sleep(0.42)
    # Kill the server by making a connection so that the serve loop doesn't block
    try:
      urllib.urlopen('http://localhost:%d/' % (self.port))
    except:
      pass
    
    sock.close()
    
  def index(self, environ, start_response):
    '''
      MUD Web Server index page
    '''
    path = environ['PATH_INFO']
    if path == '/':
      path = '/index.html'
    try:
      fp = open('web' + path)
      template = fp.readlines()
      fp.close()
      
      status = '200 OK'
      response_headers = [('Content-type', guess_type('web' + path)[0])]
      start_response(status, response_headers)
    except:
      template = "You have encountered the evil 404 monster! That basically means that we couldn't find the page you wanted, so try something else ;)"
      status = '404 NOT FOUND'
      response_headers = [('Content-type','text/plain')]
      start_response(status, response_headers)
      
      logging.info(traceback.format_exc())
    
    responsePage = ''
    
    # Get the online users
    try:
      who = '<br/>'.join(executeCommand(self.sock, 'who')[1].split('\n'))
    except:
      who = 'Error communicating with server!!!'
    
    if who == '':
      who = 'None'
    
    # Get a random map
    boards = model.Board.query.all()
    boardID = randint(0, len(boards) - 1)
    board = simplejson.loads(boards[boardID].data)
    asciiBoard = ''
    
    players = model.User.query.filter_by(board=boards[boardID].id).filter_by(online=True).all()
    
    player_results = [{'x': player.pos_x, 'y': player.pos_y, 'username': player.username} for player in players]
    
    for player in player_results:
      players.append((player['x'], player['y']))
    
    for y in range(board.get('height')):
      for x in range(board.get('width')):
        if (x, y) in players:
          asciiBoard += 'P'
        else:
          asciiBoard += board.get(str(y), {}).get(str(x), {}).get('ascii', '&nbsp;')
      asciiBoard += '<br />'
    
    # Replace special character sequences
    for line in template:
      line = line.replace('%who%', who).replace('%randmap%', str(asciiBoard))
      responsePage += line
    
    return [responsePage]
  
  def run(self):
    # Setup a connection to the server
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.connect(('localhost', self.server_port))
    executeCommand(self.sock, 'login', ['admin', 'foo'])
    
    # Start up a listener
    self.httpd = make_server('', self.port, self.index)
    welcome = 'WebServ: Startup complete. Listening on port ' + str(self.port)
    logging.info(welcome)
    print welcome
    print
    
    # Serve requests until we are killed
    while not self.killed:
      try:
        self.httpd.handle_request()
      except:
        # TODO: Error handling
        pass
    executeCommand(self.sock, 'quit')
    print 'HTTP server has terminated'